import os
import zipfile

from selenium import webdriver
from selenium.webdriver.chrome.service import Service

from fake_useragent import UserAgent


class Browser:
    """ Класс представляющий браузер """

    def get_executable_path(self) -> str:
        """ Получаем путь до драйвера """
        return os.path.abspath('scraper/chromedriver')


    def get_browser_options(self, display_browser: bool) -> webdriver.ChromeOptions:
        """ Настраиваем браузер """

        user_agent = UserAgent()
        user_agent = user_agent.chrome

        options = webdriver.ChromeOptions()
        options.add_argument(f'--user-agent={user_agent}')
        options.add_argument(f'--disable-blink-features=AutomationControlled')

        if not display_browser:  # Если браузер не нужно отображать
            options.add_argument('--headless')

        return options


    def get_browser(self, display_browser: bool = False) -> webdriver.Chrome:
        """ Получить браузер """

        browser = webdriver.Chrome(
            executable_path=self.get_executable_path(),
            options=self.get_browser_options(display_browser)
        )
        return browser


    def close_browser(self, browser: webdriver.Chrome) -> None:
        """ Закрываем браузер """

        browser.close()
        browser.quit()


class BrowserProxy(Browser):
    """ Работа браузера с прокси """

    def get_manifest_json(self) -> str:
        manifest_json = """
        {
            "version": "1.0.0",
            "manifest_version": 2,
            "name": "Chrome Proxy",
            "permissions": [
                "proxy",
                "tabs",
                "unlimitedStorage",
                "storage",
                "<all_urls>",
                "webRequest",
                "webRequestBlocking"
            ],
            "background": {
                "scripts": ["background.js"]
            },
            "minimum_chrome_version":"76.0.0"
        }
        """
        return manifest_json

    def get_background_js(
        self,
        proxy_host: str,
        proxy_port: str,
        proxy_username: str,
        proxy_password: str
    ) -> str:
        background_js = """
        let config = {
                mode: "fixed_servers",
                rules: {
                singleProxy: {
                    scheme: "http",
                    host: "%s",
                    port: parseInt(%s)
                },
                bypassList: ["localhost"]
                }
            };
        chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
        function callbackFn(details) {
            return {
                authCredentials: {
                    username: "%s",
                    password: "%s"
                }
            };
        }
        chrome.webRequest.onAuthRequired.addListener(
                    callbackFn,
                    {urls: ["<all_urls>"]},
                    ['blocking']
        );
        """ % (proxy_host, proxy_port, proxy_username, proxy_password)
        return background_js

    def set_proxy_for_browser(
        self,
        proxy,
        options: webdriver.ChromeOptions,
    ) -> webdriver.Chrome:
        """ Устанавливаем прокси для браузера """

        plugin_file = 'proxy_auth_file.zip'

        with zipfile.ZipFile(plugin_file, 'w') as file:
            manifest_json = self.get_manifest_json()
            background_js = self.get_background_js(
                proxy_host=proxy['ip'],
                proxy_port=proxy['port'],
                proxy_username=proxy['username'],
                proxy_password=proxy['password']
            )

            file.writestr('manifest.json', manifest_json)
            file.writestr('background.js', background_js)

        options.add_extension(plugin_file)

        service = Service(
            executable_path=self.get_executable_path()
        )
        browser = webdriver.Chrome(
            service=service,
            options=options
        )
        return browser


    def get_browser(
        self,
        list_of_proxy
    ) -> webdriver.Chrome:
        """ Получаем браузер с установленным прокси """

        options = self.get_browser_options(display_browser=True)

        for proxy in list_of_proxy:

            browser = self.set_proxy_for_browser(
                proxy=proxy,
                options=options
            )
            return browser
